package com.basic.common.security;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.security.Key;

/**
 * @author YanShuang
 */
public class AesDsUtil {

    private static final String charset = "UTF-8";

    /**
     * AES加密为base 64 code
     *
     * @param content    待加密的内容
     * @param encryptKey 加密密钥
     * @return 加密后的base 64 code
     */
    public static String aesEcbPkcs5Encrypt(String content, String encryptKey) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));
        byte[] bytes = cipher.doFinal(content.getBytes("utf-8"));
        return Base64.encodeBase64String(bytes);
    }

    /**
     * 将base 64 code AES解密
     *
     * @param content 待解密的base 64 code
     * @param decryptKey 解密密钥
     * @return 解密后的string
     */
    public static String aesEcbPkcs5Decrypt(String content, String decryptKey) throws Exception {
        if (StringUtils.isBlank(content)) {
            return StringUtils.EMPTY;
        }
        if (StringUtils.isBlank(decryptKey)) {
            throw new Exception("decrypt key is null");
        }
        if (decryptKey.length() != 16) {
            throw new Exception("decrypt key length error");
        }
        byte[] bytes = Base64.decodeBase64(content);
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));
        byte[] decryptBytes = cipher.doFinal(bytes);
        return new String(decryptBytes);
    }

    /**
     * AES解密
     * @param content 密文
     * @return
     * @throws Exception
     */
    public static byte[] aesCbcPkcs7decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
        Key sKeySpec = new SecretKeySpec(keyByte, "AES");
        AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
        params.init(new IvParameterSpec(ivByte));
        cipher.init(Cipher.DECRYPT_MODE, sKeySpec, params);
        byte[] result = cipher.doFinal(content);
        return result;
    }

    public static String aesCbcPkcs5decrypt(String sSrc, String sKey, String siv) throws Exception {
        if (StringUtils.isBlank(sSrc)) {
            return StringUtils.EMPTY;
        }
        if (StringUtils.isBlank(sKey)) {
            throw new Exception("decrypt key is null");
        }
        if (sKey.length() != 16) {
            throw new Exception("decrypt key length error");
        }
        byte[] Decrypt = hexToByte(sSrc);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec skeySpec = new SecretKeySpec(sKey.getBytes(charset), "AES");
        IvParameterSpec iv = new IvParameterSpec(siv.getBytes(charset));//new IvParameterSpec(getIV());
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);//使用解密模式初始化 密
        return new String(cipher.doFinal(Decrypt), charset);
    }

    public static byte[] hexToByte(String hex){
        int m = 0, n = 0;
        int byteLen = hex.length() / 2; // 每两个字符描述一个字节
        byte[] ret = new byte[byteLen];
        for (int i = 0; i < byteLen; i++) {
            m = i * 2 + 1;
            n = m + 1;
            int intVal = Integer.decode("0x" + hex.substring(i * 2, m) + hex.substring(m, n));
            ret[i] = Byte.valueOf((byte)intVal);
        }
        return ret;
    }

    public static void main(String[] args) throws Exception {
        String key = "1dbcc9627226f062";
        String key2 = "23ed789c1caf3a05";
        System.out.println("密钥：" + key);
        String content = "url：findNames.action";
        System.out.println("加密前：" + content);
        System.out.println("加密密钥和解密密钥：" + key);
        String encrypt = aesEcbPkcs5Encrypt(content, key);
        System.out.println("加密后：" + encrypt);
        String decrypt = aesEcbPkcs5Decrypt(encrypt, key);
        System.out.println("解密后：" + decrypt);
    }
}